{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1 align=\"center\"> Functions </h1>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Python Functions to Remove Duplicates from List"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 4, 10, 20, 5]\n"
     ]
    }
   ],
   "source": [
    "# Python code to remove duplicate elements from list\n",
    "\n",
    "def remove_duplicates(duplicate): \n",
    "    uniques = [] \n",
    "    for num in duplicate: \n",
    "        if num not in uniques: \n",
    "            uniques.append(num) \n",
    "    return(uniques)\n",
    "      \n",
    "duplicate = [2, 4, 10, 20, 5, 2, 20, 4] \n",
    "print(remove_duplicates(duplicate)) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another thing that is worth mentioning when you’re working with the return statement is the fact that you can use it to return multiple values. To do this, you make use of tuples."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tuple Unpacking"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples are sequences, just like lists. The differences between tuples and lists are, the tuples cannot be changed (immutable) unlike lists (mutable). <br> Tuples use parentheses, whereas lists use square brackets."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Initialize a Tuple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are two ways to initialize an empty tuple. You can initialize an empty tuple by having () with no values in them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Way 1\n",
    "emptyTuple = ()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "You can also initialize an empty tuple by using the <b>tuple</b> function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Way 2\n",
    "emptyTuple = tuple()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "A tuple with values can be initialized by making a sequence of values separated by commas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# way 1\n",
    "z = (3, 7, 4, 2)\n",
    "\n",
    "# way 2 (tuples can also can be created without parenthesis)\n",
    "z = 3, 7, 4, 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "It is important to keep in mind that if you want to create a tuple containing only one value, you need a trailing comma after your item."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# tuple with one value\n",
    "tup1 = ('Michael',)\n",
    "\n",
    "# tuple with one value\n",
    "tup2 = 'Michael', \n",
    "\n",
    "# This is a string, NOT a tuple.\n",
    "notTuple = ('Michael')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# Accessing Values in Tuples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each value in a tuple has an assigned index value. It is important to note that python is a zero indexed based language. All this means is that the first value in the tuple  is at index 0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "# Initialize a tuple\n",
    "z = (3, 7, 4, 2)\n",
    "\n",
    "# Access the first item of a tuple at index 0\n",
    "print(z[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python also supports negative indexing. Negative indexing starts from the end of the tuple. It can sometimes be more convenient to use negative indexing to get the last item in a tuple because you don't have to know the length of a tuple to access the last item."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "# print last item in the tuple\n",
    "print(z[-1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "As a reminder, you could also access the same item using positive indexes (as seen below)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "print(z[3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# Tuple slices"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Slice operations return a new tuple containing the requested items. Slices are good for getting a subset of values in your tuple. For the example code below, it will return a tuple with the items from index 0 up to and not including index 2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 7)\n"
     ]
    }
   ],
   "source": [
    "# Initialize a tuple\n",
    "z = (3, 7, 4, 2)\n",
    "\n",
    "# first index is inclusive (before the :) and last (after the :) is not.\n",
    "print(z[0:2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 7, 4)\n"
     ]
    }
   ],
   "source": [
    "# everything up to but not including index 3\n",
    "print(z[:3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "You can even make slices with negative indexes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 7, 4)\n"
     ]
    }
   ],
   "source": [
    "print(z[-4:-1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tuples are Immutable"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples are immutable which means that after initializing a tuple, it is impossible to update individual items in a tuple. As you can see in the code below, you cannot update or change the values of tuple items (this is different from [Python Lists](https://hackernoon.com/python-basics-6-lists-and-list-manipulation-a56be62b1f95) which are mutable)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "'tuple' object does not support item assignment",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-83-1ba53bfc5f04>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mz\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m7\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mz\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"fish\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: 'tuple' object does not support item assignment"
     ]
    }
   ],
   "source": [
    "z = (3, 7, 4, 2)\n",
    "\n",
    "z[1] = \"fish\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Even though tuples are immutable, it is possible to take portions of existing tuples to create new tuples as the following example demonstrates."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('Python', 'SQL', 'R')\n"
     ]
    }
   ],
   "source": [
    "# Initialize tuple\n",
    "tup1 = ('Python', 'SQL')\n",
    "\n",
    "# Initialize another Tuple\n",
    "tup2 = ('R',)\n",
    "\n",
    "# Create new tuple based on existing tuples\n",
    "new_tuple = tup1 + tup2;\n",
    "print(new_tuple)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tuple Methods"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before starting this section, let's first initialize a tuple."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Initialize a tuple\n",
    "animals = ('lama', 'sheep', 'lama', 48)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## index method"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The index method returns the first index at which a value occurs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "print(animals.index('lama'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## count method"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The count method returns the number of times a value occurs in a tuple."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "print(animals.count('lama'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Iterate through a Tuple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can iterate through the items of a tuple by using a for loop."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "lama\n",
      "sheep\n",
      "lama\n",
      "48\n"
     ]
    }
   ],
   "source": [
    "for item in ('lama', 'sheep', 'lama', 48):\n",
    "    print(item)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tuple Unpacking"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples are useful for sequence unpacking."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Value of x is 7, the value of y is 10.\n"
     ]
    }
   ],
   "source": [
    "x, y = (7, 10);\n",
    "print(\"Value of x is {}, the value of y is {}.\".format(x, y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Enumerate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The enumerate function returns a tuple containing a count for every iteration (from start which defaults to 0) and the values obtained from iterating over a sequence:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 'Steve')\n",
      "(1, 'Rachel')\n",
      "(2, 'Michael')\n",
      "(3, 'Monica')\n"
     ]
    }
   ],
   "source": [
    "friends = ('Steve', 'Rachel', 'Michael', 'Monica')\n",
    "for index, friend in enumerate(friends):\n",
    "    print(index,friend)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Advantages of Tuples over Lists"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lists and tuples are standard Python data types that store values in a sequence. A tuple is <b>immutable</b> whereas a list is <b>mutable</b>. Here are some other advantages of tuples over lists (partially from [Stack Overflow](https://stackoverflow.com/questions/1708510/python-list-vs-tuple-when-to-use-each))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Tuples are faster than lists</b>. If you're defining a constant set of values and all you're ever going to do with it is iterate through it, use a tuple instead of a list. The performance difference can be partially measured using the timeit library which allows you to time your Python code. The code below runs the code for each approach 1 million times and outputs the overall time it took in seconds."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('Tuple time: ', 0.09162306785583496)\n",
      "('List time: ', 0.4425089359283447)\n"
     ]
    }
   ],
   "source": [
    "import timeit \n",
    "print('Tuple time: ', timeit.timeit('x=(1,2,3,4,5,6,7,8,9,10,11,12)', number=1000000))\n",
    "print('List time: ', timeit.timeit('x=[1,2,3,4,5,6,7,8,9,10,11,12]', number=1000000))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some tuples can be used as dictionary keys (specifically, tuples that contain immutable values like strings, numbers, and other tuples). Lists can never be used as dictionary keys, because lists are not immutable (you can learn more about dictionaries [here](https://hackernoon.com/python-basics-10-dictionaries-and-dictionary-methods-4e9efa70f5b9))."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tuples can be dictionary keys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{('is', 'a'): 12, ('this', 'is'): 23, ('a', 'sentence'): 2}\n"
     ]
    }
   ],
   "source": [
    "bigramsTupleDict = {('this', 'is'): 23,\n",
    "                    ('is', 'a'): 12,\n",
    "                    ('a', 'sentence'): 2}\n",
    "\n",
    "print(bigramsTupleDict)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lists can NOT be dictionary keys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-99-834f1c969506>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m bigramsListDict = {['this', 'is']: 23,\n\u001b[0m\u001b[1;32m      2\u001b[0m                    \u001b[0;34m[\u001b[0m\u001b[0;34m'is'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'a'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m12\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m                    ['a', 'sentence']: 2}\n\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbigramsListDict\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "bigramsListDict = {['this', 'is']: 23,\n",
    "                   ['is', 'a']: 12,\n",
    "                   ['a', 'sentence']: 2}\n",
    "\n",
    "print(bigramsListDict)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tuples can be values in a set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "set([('is', 'a'), ('this', 'is'), ('a', 'sentence')])\n"
     ]
    }
   ],
   "source": [
    "graphicDesigner = {('this', 'is'),\n",
    "                   ('is', 'a'),\n",
    "                   ('a', 'sentence')}\n",
    "print(graphicDesigner)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Lists can NOT be values in a set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-49-008c17adfe8f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m graphicDesigner = {['this', 'is'],\n\u001b[1;32m      2\u001b[0m                    \u001b[0;34m[\u001b[0m\u001b[0;34m'is'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'a'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m                    ['a', 'sentence']}\n\u001b[0m\u001b[1;32m      4\u001b[0m \u001b[0;32mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgraphicDesigner\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "graphicDesigner = {['this', 'is'],\n",
    "                   ['is', 'a'],\n",
    "                   ['a', 'sentence']}\n",
    "print(graphicDesigner)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Task: Generating Fibonacci Sequence in Python"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fibonacci sequence is an integer sequence characterized by the fact that every number after the first two is the sum of the two preceding ones. By definition, the first two numbers in the Fibonacci sequence are either 1 and 1 (<b>which is how I like to code it</b>), or 0 and 1, depending on the chosen starting point of the sequence, and each subsequent number is the sum of the previous two."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 1 2 3 5 8 13 21 34 55\n"
     ]
    }
   ],
   "source": [
    "print(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. Using looping technique, write a Python program which prints out the first 10 Fibonacci numbers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('Fib(a): ', 1, 'b is: ', 1)\n",
      "('Fib(a): ', 1, 'b is: ', 2)\n",
      "('Fib(a): ', 2, 'b is: ', 3)\n",
      "('Fib(a): ', 3, 'b is: ', 5)\n",
      "('Fib(a): ', 5, 'b is: ', 8)\n",
      "('Fib(a): ', 8, 'b is: ', 13)\n",
      "('Fib(a): ', 13, 'b is: ', 21)\n",
      "('Fib(a): ', 21, 'b is: ', 34)\n",
      "('Fib(a): ', 34, 'b is: ', 55)\n",
      "('Fib(a): ', 55, 'b is: ', 89)\n"
     ]
    }
   ],
   "source": [
    "# Note, there are better ways to code this which I will go over in later videos\n",
    "a,b = 1,1\n",
    "for i in range(10):\n",
    "    print(\"Fib(a): \", a, \"b is: \", b)\n",
    "    a,b = b,a+b   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**if this tutorial doesn't cover what you are looking for, please leave a comment on the youtube video and I will try to cover what you are interested in. (Please subscribe if you can!)**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://www.youtube.com/watch?v=gUHeaQ0qZaw"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [conda env:py36]",
   "language": "python",
   "name": "conda-env-py36-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
